package com.lxl.message;

import java.util.*;

import static com.lxl.message.TemplateStringUtils.*;

public class TemplateStructure {
    public static void main(String[] args){
        String text ="$root$=\n" +
                "        {\n" +
                "            #time#=#TIME#,\n" +
                "            $id$=/rows/row/id,\n" +
                "            $taskLocalConfigFileName$=/rows/row/taskLocalConfigFileName,\n" +
                "            $age$=/rows/row/age,\n" +
                "            $phones$=\n" +
                "            {\n" +
                "                $phone$=/rows/row/phone,\n" +
                "            },\n" +
                "            $addressinfo.address$=\n" +
                "            {\n" +
                "                $addname$=/rows/row/address,\n" +
                "                $urls$=\n" +
                "                {\n" +
                "                    $url$=/rows/row/url\n" +
                "                },\n" +
                "                $langs.lang$=\n" +
                "                {\n" +
                "                    $cn$=/rows/row/cn,\n" +
                "                    $en$=/rows/row/en\n" +
                "                }\n" +
                "            }\n" +
                "        }";
        text = removeBlank(text);
        TemplateStructure structure = build(text);
        structure.traverse2();
    }

    private Map<String, String> object;
    private Map<String, TemplateStructure> array;

    private TemplateStructure(){
        object = new LinkedHashMap<>();
        array = new LinkedHashMap<>();
    }

    public static TemplateStructure build(String content){
        TemplateStructure structure = new TemplateStructure();

        List<String> blockList = getBlocks(content);
        for (String block : blockList){
            String[] temp = getKeyAndValue(block);
            if (isBracketed(temp[1])){//array
                structure.array.put(temp[0], build(removeBracket(temp[1])));
            }else{
                structure.object.put(temp[0], temp[1]);
            }
        }

        return structure;
    }

    public void traverse(){
        if (hasObject()){
            for (Map.Entry<String, String> entry : object.entrySet()){
                System.out.println("In object:[ " + entry.getKey() + "," + entry.getValue() + " ]");
            }
        }

        if (hasArray()){
            for (Map.Entry<String, TemplateStructure> entry : array.entrySet()){
                System.out.println("In array: " + entry.getKey());
                entry.getValue().traverse();
                System.out.println("Out array: " + entry.getKey());
            }
        }
    }

    public void traverse2(){

        if (hasObject()){
            for (Map.Entry<String, String> entry : object.entrySet()){
                System.out.println("Map add object:[ " + entry.getKey() + "," + entry.getValue() + " ]");
            }
        }

        if (hasArray()){
            Iterator<Map.Entry<String, TemplateStructure>> iterator= array.entrySet().iterator();
            Stack<Iterator<Map.Entry<String, TemplateStructure>>> stack = new Stack<>();
            while(iterator.hasNext() || !stack.isEmpty()) {
                if (!iterator.hasNext() && !stack.isEmpty()){
                    iterator = stack.pop();
                    System.out.println("out");
                    continue;
                }

                Map.Entry<String, TemplateStructure> entry = iterator.next();
                System.out.println("In array:" + entry.getKey());
                if (entry.getValue().hasObject()){
                    for (Map.Entry<String, String> innerObj : entry.getValue().object.entrySet()){
                        System.out.println("Map add object:[ " + innerObj.getKey() + "," + innerObj.getValue() + " ]");
                    }
                }

                if (entry.getValue().hasArray()){
                    stack.push(iterator);
                    iterator = (entry.getValue()).array.entrySet().iterator();
                }
            }
        }
    }

    public boolean hasObject(){
        return object.size() > 0;
    }

    public boolean hasArray(){
        return array.size() > 0;
    }

    public Map<String, String> getObject() {
        return object;
    }

    public Map<String, TemplateStructure> getArray() {
        return array;
    }

    private static List<String> getBlocks(String content){
        List<String> blocks = new LinkedList<>();//分解成块的列表
        Map<Character, Character> bracketPair = new HashMap<>();//保存'{','}'
        Stack<Character> charStack = new Stack<>();//括号匹配

        int conLength = content.length();
        int blockStart = 0;//截取的初始位置
        boolean isIn = false;//使嵌套中的,无效

        bracketPair.put('}','{');

        for (int i=0 ; i<conLength ; i++){
            char ch = content.charAt(i);
            if (ch == ',' && !isIn ){
                blocks.add(content.substring(blockStart, i));
                blockStart = i+1;
                continue;
            }

            if (bracketPair.containsValue(ch)){//若是'{'
                isIn = true;
                charStack.push(ch);
            }else if (bracketPair.containsKey(ch)){//若是'}'
                if (charStack.isEmpty()) {//栈中无'{'与其匹配
                    return null;
                }

                if (charStack.peek().equals(bracketPair.get(ch))){
                    charStack.pop();
                    if (charStack.isEmpty()){
                        isIn = false;
                    }
                }
            }

            if (i == conLength-1){
                blocks.add(content.substring(blockStart, conLength));
            }
        }
        return blocks;
    }
}
